using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using ActiveDs;
using System.DirectoryServices;
using System.Web.Security;
using System.Text.RegularExpressions;
using System.Configuration;


namespace ADAMPasswordChange
{
    [Guid("14c435b6-ebab-465f-9679-96b2d54f45d4")]
    public class ADAMPassword : Microsoft.SharePoint.WebPartPages.WebPart
    {
        public ADAMPassword()
        {

            this.ExportMode = WebPartExportMode.All;
        }

        private TextBox oldpassword;
        private TextBox newpassword;
        private TextBox checknewpassword;

        private string strLoginName;
        private string strUserName;
        private string strMyuser;

        private LinkButton btn;
        private Label output;
        private Label UserPolicyText;
        const int AD_ENABLED = 512;
        const int AD_DISABLED = 514;
        const int AD_NEVER_EXPIRE = 65536;

        protected override void CreateChildControls()
        {
            this.output = new Label();
            this.output.Text = string.Empty;
            this.Controls.Add(output);

            this.UserPolicyText = new Label();
            this.UserPolicyText.Text = "<b><u><p>Password Policy</b></u><br>Password must meet the following minimum requirements:</p><ul><li>Should be a minimum of 10 characters long.</li><li>Should contain at least one English uppercase character (A through Z).</li><li>Should contain at least one English lowercase character (a through z). </li><li>Should contain at least one Base 10 digits (0 through 9). </li><li>Should contain at least one Non-alphabetic characters (for example, !, $, #, %).</li></ul><p>For further assistance, contact <a href=mailto:ashishkanoongo@hotmail.com?subject=Password%20Change%20issues>ashishkanoongo@hotmail.com</a>.</p>" + "<br><br>";
            this.Controls.Add(UserPolicyText);
            base.CreateChildControls();

            this.oldpassword = new TextBox();
            this.oldpassword.TextMode = TextBoxMode.Password;
            this.Controls.Add(oldpassword);

            this.newpassword = new TextBox();
            this.newpassword.TextMode = TextBoxMode.Password;
            this.Controls.Add(newpassword);

            this.checknewpassword = new TextBox();
            this.checknewpassword.TextMode = TextBoxMode.Password;
            this.Controls.Add(checknewpassword);

            this.btn = new LinkButton();
            this.btn.Click += new EventHandler(btn_Click);
            this.btn.Text = "Change Password Now";
            this.Controls.Add(btn);

        }

        void btn_Click(object sender, EventArgs e)
        {

            output.Text = string.Empty;
            SPSite site = SPContext.Current.Site;
            SPWeb web = site.OpenWeb();
            //UserPolicyText.Te = string.Empty;
            string checkPassword = newpassword.Text.ToString().Trim();
            if (checkPassword.Length > 0)
            {
                if (!System.Text.RegularExpressions.Regex.IsMatch(checkPassword,
                                                   @"^(?=.{10,})(?=.*\d)(?=.*[@#$%^&+=]).*$"))
                {
                    output.Text += "<br>" + "<font color='#FF0000'><b>Please enter password  as per policy as mentioned below.</b></font>" + "<br><br>";
                    return;
                }
            }
            if (newpassword.Text.ToString() != checknewpassword.Text.ToString())
            {
                output.Text += "<br>" + "<b><font color='#FF0000'>Passwords don't match....</font></b>" + "<br><br>";
                return;
            }
            else
            {
                Boolean NTUser = true;
                try
                {

                    GetUserName();

                    if (strLoginName != @"SHAREPOINT\SYSTEM")
                    {

                        if (!strLoginName.Contains(@"DOMAINNAME\"))
                        {
                            //forms auth user

                            NTUser = false;
                        }
                    }

                }
                catch
                {
                    NTUser = false;
                }

                if (NTUser)
                {
                    output.Text += "NT User - </b>";

                }
                else
                {
                    try
                    {

                        const long ADS_OPTION_PASSWORD_PORTNUMBER = 6;
                        const long ADS_OPTION_PASSWORD_METHOD = 7;
                        const int ADS_PASSWORD_ENCODE_REQUIRE_SSL = 0;
                        const int ADS_PASSWORD_ENCODE_CLEAR = 1;

                        AuthenticationTypes AuthTypes;  // Authentication flags.
                        int intPort;                    // Port for instance.
                        DirectoryEntry objUser;         // User object.
                        string strPath;                 // Server path.
                        string strPort;                 // Port for instance.
                        string strServer;               // DNS name of the computer with
                        //   the AD LDS installation.
                        string strUser;                 // User DN.

                        // Construct the binding string.
                        //Add following in your web.config under <appSettings>
                        //<add key="AdamServerName" value="Your Server Name" />
                        //<add key="AdamSource" value=";OU=ADAM Users,O=ADAM,C=US" /> 

                        strServer = System.Configuration.ConfigurationManager.AppSettings["AdamServerName"];
                        strPort = "389";
                        string strAdamSource = System.Configuration.ConfigurationManager.AppSettings["AdamSource"];
                        strUser = "CN=" + strUserName.ToString().Trim() + strAdamSource.ToString(); 
                        
                        strPath = String.Concat("LDAP://", strServer,
                            ":", strPort, "/", strUser);
                        // Set authentication flags.
                        // For non-secure connection, use LDAP port and
                        //  ADS_USE_SIGNING |
                        //  ADS_USE_SEALING |
                        //  ADS_SECURE_AUTHENTICATION
                        // For secure connection, use SSL port and
                        //  ADS_USE_SSL | ADS_SECURE_AUTHENTICATION
                        //AuthTypes = AuthenticationTypes.Signing | AuthenticationTypes.Sealing | AuthenticationTypes.Secure;
                        AuthTypes = AuthenticationTypes.ServerBind;
                        output.Text += strUserName.ToString().Trim() + " - " + oldpassword.Text.ToString().Trim();
                        // Bind to user object using LDAP port.
                        try
                        {
                            objUser = new DirectoryEntry(
                                strPath, strUserName.ToString().Trim(), oldpassword.Text.ToString().Trim(), AuthTypes);
                            objUser.RefreshCache();
                        }
                        catch (Exception ex)
                        {
                            if (ex.Message.Contains("unknown user name or bad password"))
                            {
                                output.Text = "<br>" + "<b><font color='#FF0000'>Please enter your correct current password.</font></b>" + "<br><br>"; ;
                            }
                            else
                            {
                                output.Text = "<br>" + "<font color='#FF0000'>" + "<b>Error:   Bind failed." + " - " + ex.Message + "</b></font>" + "<br>";
                            }

                            return;
                        }
                        
                        // Set port number, method, and password.
                        intPort = Int32.Parse(strPort);
                        try
                        {
                            //  Be aware that, for security, a password should
                            //  not be entered in code, but should be obtained
                            //  from the user interface.
                            objUser.Invoke("SetOption", new object[] { ADS_OPTION_PASSWORD_PORTNUMBER, intPort });
                            objUser.Invoke("SetOption", new object[] { ADS_OPTION_PASSWORD_METHOD, ADS_PASSWORD_ENCODE_CLEAR });
                            objUser.Invoke("SetPassword", new object[] { newpassword.Text.ToString() });
                            objUser.CommitChanges();
                        }
                        catch (Exception ex1)
                        {
                            output.Text = "<br>" + "<b><font color='#FF0000'>Password Failed. </font></b>" + ex1.Message + "<br>";

                            return;
                        }
                        output.Text = "<br>" + "<b><font color='#0000FF'>Password is changed successfully.</b></font>" + "<br><br>";
                        return;

                    }
                    catch (Exception error)
                    {
                        output.Text = "<br>" + "<b><font color='#FF0000'>User Password Change Error:\n" + error.StackTrace.ToString() + "\n" + error.Message.ToString() + "</font>" + "<br>";
                    }
                }
                //---------
            }
        }


        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            EnsureChildControls();
            GetUserName();
            if (strLoginName != string.Empty)
            {
                output.RenderControl(writer);
                writer.Write("<table border=0>");
                writer.Write("<tr>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("User Name:");
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'><b>");
                writer.Write(strLoginName);
                writer.Write("<b></td>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("</td>");
                writer.Write("</tr>");
                writer.Write("<tr><td colspan='3'></td></tr>");
                writer.Write("<tr>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("Current password:");
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                oldpassword.RenderControl(writer);
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("</td>");
                writer.Write("</tr>");
                writer.Write("<tr valign='top'>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("New password:");
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                newpassword.RenderControl(writer);
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("</td>");
                writer.Write("</tr>");
                writer.Write("<tr valign='top'>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("Confirm new password:");
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                checknewpassword.RenderControl(writer);
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("</tr>");
                writer.Write("<tr valign='top'>");
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                btn.RenderControl(writer);
                writer.Write("</td>");
                writer.Write("<td class='ms-vb'>");
                writer.Write("</td>");
                writer.Write("</tr>");
                writer.Write("</table>");
                UserPolicyText.RenderControl(writer);
            }
            else
            {
                output.RenderControl(writer);
            }
        }

        string GetUserName()
        {
            strUserName = "";

            try
            {
                SPWeb webContext = SPControl.GetContextWeb(Context);

                strLoginName = webContext.CurrentUser.Name.ToString();
                strMyuser = webContext.CurrentUser.Name.ToLower();
                strUserName = webContext.CurrentUser.LoginName.ToLower();

                string[] x = strUserName.Split(':');
                if (x.Length > 1)
                {
                    strUserName = x[1];
                }
                else
                {
                    strUserName = x[0];
                }
            }
            catch
            {
                strUserName = "";
            }
            return strUserName;
        }
    }
}
